<script setup lang="ts">
import {getCurrentInstance, onMounted, ref} from 'vue';
import {
  clipRoundRect,
  fillRoundRect,
  getImageModeLeftTopWidthHeight,
  getWidthByTextNum,
  getWidthByTextNum1,
  loadFace,
  loadImage2d,
  roundRect,
  rpx2px
} from "./canvasUtils.js";
import {onReady} from "@dcloudio/uni-app";
import SvgPath from "./svgPath";
import {DrawData, NodeElement, ShowImage} from "./types";
import md5 from './md5';

const emit = defineEmits<{
  (e: 'change', path: string, imageInfo: ShowImage, showNodeElements: NodeElement[]): void
  (e: 'drawError', error: Error): void
  (e: 'redrawing', isRedrawing: boolean): void
  (e: 'nodeClick', item: NodeElement[]): void
}>();

const currentInstance = getCurrentInstance();


const props = defineProps<{
  drawData: DrawData
}>()

let nodes: NodeElement[] = [];
let nodesDrawFinish: NodeElement[] = [];

const getTextOverflowString = (textOverflow: string) => {
  if (textOverflow === 'ellipsis') {
    return '...'
  }
  if (textOverflow) {
    return unescape(textOverflow.replace('&#x', '\%u').replace(';', ''));
  }
  return '';
}

let imageRect = null;

let redrawing = false;
let tempDrawData: DrawData | null | undefined;
let nextRedraw = false;
let stt = 0;

function copyObj(obj) {
  return JSON.parse(JSON.stringify(obj));
}

function deepClone(target: any) {
  // 定义一个变量
  let result;
  // 如果当前需要深拷贝的是一个对象的话
  if (typeof target === 'object') {
    // 如果是一个数组的话
    if (Array.isArray(target)) {
      result = []; // 将result赋值为一个数组，并且执行遍历
      for (let i in target) {
        // 递归克隆数组中的每一项
        result.push(deepClone(target[i]))
      }
      // 判断如果当前的值是null的话；直接赋值为null
    } else if (target === null) {
      result = null;
      // 判断如果当前的值是一个RegExp对象的话，直接赋值
    } else if (target.constructor === RegExp) {
      result = target;
    } else {
      // 否则是普通对象，直接for in循环，递归赋值对象的所有值
      result = {};
      for (let i in target) {
        result[i] = deepClone(target[i]);
      }
    }
    // 如果不是对象的话，就是基本数据类型，那么直接赋值
  } else {
    result = target;
  }
  // 返回最终结果
  return result;
}

function md5Str(str: string) {
  const md5s = md5(str);
  return md5s;
}


const resourcesMap = new Map();

async function preloadFaces(data) {

  //加载图标
  const resourcesFaces = [];
  if (data.faces && data.faces.length > 0) {
    const loadFaces = data.faces.filter(i => i.url && i.name).filter(i => !resourcesMap.has(i.url));

    for (let i = 0; i < loadFaces.length; i++) {
      const face = loadFaces[i];
      console.log('face', face);
      resourcesFaces.push(loadFace(face.name, face.url));
    }
    let all = await Promise.all(resourcesFaces);
    for (let i = 0; i < loadFaces.length; i++) {
      const node = loadFaces[i];
      resourcesMap.set(node.url, all[i]);
    }
  }
  return Promise.resolve();
}

async function preloadImages(data) {
  const resourcesImages = [];


  //加载所有图片
  let images = nodes.filter(i => i.resourceType === 'image').filter(i => i.url);
  images.forEach(i => {
    resourcesImages.push(loadImage2d(i.url));
  })

  let all = await Promise.all(resourcesImages);

  for (let i = 0; i < images.length; i++) {
    const node = images[i];
    resourcesMap.set(md5Str(node.url), all[i]);
  }

  return all;
}

async function preloadAllResources(data?: DrawData) {
  await Promise.all([preloadFaces(data), preloadImages(data)]);
}

const reDraw = async (data?: DrawData) => {
  if (redrawing) {
    nextRedraw = true;
    tempDrawData = data;
    return;
  }

  if (!canvas) {
    return;
  }
  if (!data) {
    return;
  }

  nodesConversion(data.nodeElements);

  width = rpx2px(data.width);
  height = rpx2px(data.height);


  canvas.width = width;
  canvas.height = height;


  redrawing = true;

  try {
    await preloadAllResources(data);

    await drawNodeElements();
  } catch (e) {
    emit('drawError', e);
  }


  nodesDrawFinish = nodes;
  redrawing = false;
  image.value = canvas.toDataURL("image/png");

  uni.createSelectorQuery().in(currentInstance).select(`#${id} #mpCardCanvas`).boundingClientRect((res) => {
    imageRect = res;
    zoom = imageRect.width / width;
    emit('change', image.value, {width, height, showWidth: width * zoom, showHeight: height * zoom, zoom}, nodes);
    if (nextRedraw) {
      nextRedraw = false;
      if (tempDrawData) {
        reDraw(tempDrawData);
        tempDrawData = null;
      }
    }
  }).exec()


}
defineExpose({
  reDraw,
  getNodeElementByPoint
});
const image = ref('');
const canvasId = 'mpCardCanvas';
const canvasTempId = 'mpCardCanvasTemp';
let width = rpx2px(props.drawData.width);
let height = rpx2px(props.drawData.height);

let canvasTempWidth = 1000;
let canvasTempHeight = 1000;
let fontFamily = ref('');

let canvasContext = null;
let imageCanvasContext = null;
let canvas = null;
let canvasImage = null;


function drawIcon(node: NodeElement) {

  let svgPath = new SvgPath(node.d);
  let [svgWidth, svgHeight] = svgPath.size;
  const scaleX = node.css.width / svgWidth;
  const scaleY = node.css.height / svgHeight;
  svgPath.save()
      .beginPath()
      .trim()
      .scale(scaleX, scaleY)
      .translate(node.css.left, node.css.top)
      .to(canvasContext);
  canvasContext.clip();

  canvasContext.fillStyle = node.css.color;
  canvasContext.fill();

}

async function drawImageIconNode(node: NodeElement) {


  canvasContext.save();

  //旋转
  node.css.angle = node.css.angle || 0;
  const angle = node.css.angle;
  canvasContext.translate(node.css.left + node.css.width / 2, node.css.top + node.css.height / 2);
  canvasContext.rotate(angle * Math.PI / 180);
  canvasContext.translate(-(node.css.left + node.css.width / 2), -(node.css.top + node.css.height / 2));

  drawShadow(node);

  //锁定区域
  clipRoundRect(canvasContext, node.css.left, node.css.top, node.css.width, node.css.height, node.css.borderRadius);

  //填充背景
  darwBg(node);

  drawIcon(node);
  node.width = node.css.width;
  node.height = node.css.height;

  //填充边框
  darwBorder(node);

  //解锁区域
  canvasContext.restore();

}


function calcDynamicLocation(item: NodeElement, drawNodes: NodeElement[]) {
  let dynamicLocation = item.css.dynamicLocation;
  //获取上一个元素
  let preItem = drawNodes[drawNodes.length - 1];
  let left = item.css.left;
  let top = item.css.top;
  if (preItem) {
    left = preItem.css.left;
    top = preItem.css.top;
    if (dynamicLocation.direction === 'left') {
      left = preItem.css.left - preItem.width;
    } else if (dynamicLocation.direction === 'top') {
      top = preItem.css.top - preItem.height;
    } else if (dynamicLocation.direction === 'right') {
      left = preItem.css.left + preItem.width;
    } else if (dynamicLocation.direction === 'bottom') {
      top = preItem.css.top + preItem.height;
    }
    left = left + dynamicLocation.offset.left;
    top = top + dynamicLocation.offset.top;
    return {left, top};
  }
  return {left, top};

}

async function drawNodeElements() {
  const drawNodes: NodeElement[] = [];

  for (let i = 0; i < nodes.length; i++) {
    const item = nodes[i];
    if (item.css.dynamicLocation) {
      const {left, top} = calcDynamicLocation(item, drawNodes);
      item.css.left = left;
      item.css.top = top;
    }
    canvasContext.globalAlpha = item.css.opacity;
    if (item.resourceType === 'text') {
      await fillTextNode(item);
    } else if (item.resourceType === 'image') {
      await drawImageNode(item);
    } else if (item.resourceType === 'icon') {
      await drawImageIconNode(item);
    } else if (item.resourceType === 'group') {
      drawCurrentGroup = item;
      await drawGroupNode(item);
    }
    drawNodes.push(item);
    canvasContext.globalAlpha = 0;
  }
}

let drawCurrentGroup = null;
let groupLeftTopAccumulate = {
  left: 0,
  top: 0
};

async function drawGroupNode(group: NodeElement) {

  //组定位累加
  groupLeftTopAccumulate.left += group.css.left;
  groupLeftTopAccumulate.top += group.css.top;

  //组开始 锁定组区域
  // clipRoundRect(canvasContext, groupLeftTopAccumulate.left, groupLeftTopAccumulate.top, group.css.width, group.css.height, group.css.borderRadius);
  for (let i = 0; i < group.children.length; i++) {
    const item = group.children[i];
    if (item.resourceType === 'group') {
      drawCurrentGroup = item;
      item.width = group.css.width;
      item.height = group.css.height;
      await drawGroupNode(item);
      return;
    }
    item.css.left += groupLeftTopAccumulate.left;
    item.css.top += groupLeftTopAccumulate.top;
    if (item.resourceType === 'text') {
      await fillTextNode(item);
    } else if (item.resourceType === 'image') {
      await drawImageNode(item);
    } else if (item.resourceType === 'icon') {
      await drawImageIconNode(item);
    }
  }
  groupLeftTopAccumulate.left = 0;
  groupLeftTopAccumulate.top = 0;


  //组结束 解锁组区域
  // canvasContext.restore();


}


function drawText(node: NodeElement) {
  let tFontSize = 30;

  if (node.css.shadowColor && node.css.shadowBlur > 0) {
    canvasContext.shadowOffsetX = node.css.shadowOffsetX;
    canvasContext.shadowOffsetY = node.css.shadowOffsetY;
    canvasContext.shadowColor = node.css.shadowColor;
    canvasContext.shadowBlur = node.css.shadowBlur;
    canvasContext.fillStyle = node.css.shadowColor;
  }

  canvasContext.textBaseline = 'top';
  let tFont = '';
  if (node.css.font) {
    tFont = node.css.font.replace(/(\d+)r?px/g, (r, fontSize) => {
      if (r.indexOf('r') !== -1) {
        tFontSize = rpx2px(+fontSize);
        return tFontSize + 'px';
      }
      tFontSize = +fontSize;
      return r
    })
  } else {
    tFontSize = +node.css.fontSize;
    tFont = `${node.css.fontSize}px ${node.css.fontFamily}`
  }

  canvasContext.fillStyle = node.css.color;
  canvasContext.font = tFont;
  //计算文本分成几行 并分成行内容数组

  const rText = unescape(node.text.replace('&#x', '\%u').replace(';', ''));
  const textR = canvasContext.measureText(rText);

  function _textAutoWidthHetght() {

    const textR = canvasContext.measureText(rText);
    node.width = textR.width;

    node.height = tFontSize;
    let maxWidth = width - node.css.left;
    let isOverflow = node.width > maxWidth;
    if (node.css.maxWidth > 0 && node.width > node.css.maxWidth) {
      isOverflow = true;
      maxWidth = node.css.maxWidth;
      node.width = maxWidth;
    }
    if (isOverflow) {

      const num = getWidthByTextNum(canvasContext, rText, maxWidth);

      //处理文字旋转
      //旋转

      canvasContext.save();
      node.css.angle = node.css.angle || 0;
      const angle = node.css.angle;
      canvasContext.translate(node.css.left + node.width / 2, node.css.top + node.height / 2);
      canvasContext.rotate(angle * Math.PI / 180);
      canvasContext.translate(-(node.css.left + node.width / 2), -(node.css.top + node.height / 2));

      const texta = rText.substring(0, num);
      let textOverflowString = getTextOverflowString(node.css.textOverflow);
      const textWidth = canvasContext.measureText(textOverflowString).width;
      const text = texta.split('').reverse().join('');
      const tNum = getWidthByTextNum1(canvasContext, text, textWidth);
      canvasContext.fillText(texta.substring(0, texta.length - tNum) + getTextOverflowString(node.css.textOverflow), node.css.left, node.css.top + 2);
      canvasContext.restore();

    } else {

      canvasContext.save();
      node.css.angle = node.css.angle || 0;
      const angle = node.css.angle;
      canvasContext.translate(node.css.left + node.width / 2, node.css.top + node.height / 2);
      canvasContext.rotate(angle * Math.PI / 180);
      canvasContext.translate(-(node.css.left + node.width / 2), -(node.css.top + node.height / 2));

      canvasContext.fillText(rText, node.css.left, node.css.top + 2);
      canvasContext.restore();
    }
    //厦门市软件园厦门市软件园二期观日路24号楼之二202室二期观日路24号楼之二202室
  }

  if (node.css.width <= 0 || node.css.height <= 0) {
    _textAutoWidthHetght();
  } else {

    const lineMaxWidth = node.css.width > width - node.css.left ? width - node.css.left : node.css.width;
    let lineWidth = node.css.width < lineMaxWidth ? node.css.width : lineMaxWidth;
    let lineMaxHeight = node.css.height > height - node.css.top ? height - node.css.top : node.css.height;

    //向上取整
    const lineNum = Math.ceil(textR.width / lineWidth);
    const lineData = [];
    let showMaxLine = 0;

    node.height = 0;
    node.width = lineWidth;


    let lineStartIndex = 0;

    for (let i = 0; i < lineNum; i++) {
      let widthByTextNum = getWidthByTextNum(canvasContext, rText.substring(lineStartIndex), lineWidth);

      //最多行限制
      if (i > node.css.maxLine - 1) {
        if (lineStartIndex < rText.length) {
          let textOverflowString = getTextOverflowString(node.css.textOverflow);
          const textWidth = canvasContext.measureText(textOverflowString).width;
          const text = lineData[i - 1].text.split('').reverse().join('');
          const tNum = getWidthByTextNum1(canvasContext, text, textWidth);
          lineData[i - 1].text = lineData[i - 1].text.substring(0, lineData[i - 1].text.length - tNum - 1) + textOverflowString;
        }
        break;
      }

      let fontHeight = tFontSize;
      let lineHeight = fontHeight;
      const lineSpacing = node.css.lineSpacing || 0;

      node.height += lineHeight + lineSpacing;
      if (node.height > lineMaxHeight) {
        if (i > 0) {
          node.height -= lineHeight + lineSpacing;
          if (lineStartIndex + widthByTextNum < rText.length) {
            let textOverflowString = getTextOverflowString(node.css.textOverflow);
            const textWidth = canvasContext.measureText(textOverflowString).width;
            const tNum = getWidthByTextNum1(canvasContext, lineData[i - 1].text.split('').reverse().join(''), textWidth);
            lineData[i - 1].text = lineData[i - 1].text.substring(0, lineData[i - 1].text.length - tNum - 1) + textOverflowString;
          }
        }

        break;
      }


      if (i === lineNum - 1) {
        widthByTextNum = rText.length - lineStartIndex;
      }
      let lineContent = rText.substring(lineStartIndex, lineStartIndex + widthByTextNum);

      showMaxLine = i + 1;

      lineData[i] = {
        text: lineContent,
        width: lineWidth,
        lineNum: i
      }

      lineStartIndex += widthByTextNum;

      const textR = canvasContext.measureText(lineData[i].text);

      let top = node.css.top + lineData[i].lineNum * (lineHeight + lineSpacing);
      let left = node.css.left;
      let myNodeWidth = textR.width;

      if (node.css.textAlign === 'center') {
        left = node.css.left + (node.css.width - myNodeWidth/*自己的宽度*/) / 2;
      } else if (node.css.textAlign === 'right') {
        left = node.css.left + node.css.width - myNodeWidth;
      }
      lineData[i].top = top;
      lineData[i].left = left;
    }


    canvasContext.save();
    node.css.angle = node.css.angle || 0;
    const angle = node.css.angle;
    canvasContext.translate(node.css.left + node.width / 2, node.css.top + node.height / 2);
    canvasContext.rotate(angle * Math.PI / 180);
    canvasContext.translate(-(node.css.left + node.width / 2), -(node.css.top + node.height / 2));

    for (let i = 0; i < showMaxLine; i++) {
      //支持文字垂直居中
      if (node.css.textAlign === 'center') {
        const topCenter = (node.css.height - node.height) / 2;
        canvasContext.fillText(lineData[i].text, lineData[i].left, lineData[i].top + topCenter + 2);
      } else {
        canvasContext.fillText(lineData[i].text, lineData[i].left, lineData[i].top + 2);
      }
    }
    node.height = node.css.height;
    canvasContext.restore();

  }

  if (node.css.shadowColor && node.css.shadowBlur > 0) {
    canvasContext.shadowOffsetX = 0;
    canvasContext.shadowOffsetY = 0;
    canvasContext.shadowColor = 'transparent';
    canvasContext.shadowBlur = 0;
  }

  // canvasContext.shadowColor = 'transparent';
}


async function drawImage(node: NodeElement) {
  if (!node.url) {
    console.warn('图片地址为空', node.url);
    return;
  }
  const image = resourcesMap.get(md5Str(node.url));

  const [left, top, width, height] = getImageModeLeftTopWidthHeight(image, node);
  canvasContext.save(); // 保存当前绘图状态

  //图片处理

  // const newImage = await imageDispose(image,node);
  canvasContext.globalCompositeOperation = 'source-over';
  canvasContext.drawImage(image, left, top, width, height);
  canvasContext.restore();

}

async function imageDispose(image,node: NodeElement){

  canvasImage.width = image.width;
  canvasImage.height = image.height;
  imageCanvasContext.clearRect(0, 0, canvasImage.width, canvasImage.height);
  imageCanvasContext.save();
  if(node.css.mirrorImage){
    if(node.css.mirrorImage === 'horizontal'){
      imageCanvasContext.scale(1, -1); // 垂直镜像
      imageCanvasContext.drawImage(image, 0,  -image.height);
    }else if(node.css.mirrorImage === 'vertical'){
      imageCanvasContext.scale(-1, 1); // 水平镜像
      imageCanvasContext.drawImage(image, - image.width, 0);
    }else{
      imageCanvasContext.scale(-1, -1); // 水平镜像
      imageCanvasContext.drawImage(image,  - image.width, - image.height);
    }
  }else{
    imageCanvasContext.drawImage(image, 0, 0);
  }
  imageCanvasContext.restore();
  //蒙版效果
  if (node.css.maskImage) {
    const image = await loadImage2d(node.css.maskImage);
    imageCanvasContext.globalCompositeOperation = 'destination-in';
    imageCanvasContext.drawImage(image, 0,0,canvasImage.width,canvasImage.height);
  }

  return await loadImage2d(canvasImage.toDataURL('image/png'));

}


function darwBg(node: NodeElement) {
  if (node.css.backgroundColor) {
    if (Array.isArray(node.css.backgroundColor)) {
      let grd;
      switch (node.css.backgroundColorGradientDirection) {
        case "to bottom":
          grd = canvasContext.createLinearGradient(node.css.left, node.css.top, node.css.left, node.css.top + node.css.height);
          break;
        case "to top":
          grd = canvasContext.createLinearGradient(node.css.left, node.css.top + node.css.height,
              node.css.left, node.css.top);
          break;
        case "to right":
          grd = canvasContext.createLinearGradient(node.css.left, node.css.top, node.css.left + node.css.width, node.css.top);
          break;
        case "to left":
          grd = canvasContext.createLinearGradient(node.css.left + node.css.width, node.css.top
              , node.css.left, node.css.top);
          break;
        default:
          grd = canvasContext.createLinearGradient(node.css.left, node.css.top, node.css.left, node.css.top + node.css.height);
      }

      node.css.backgroundColor.forEach((item, index) => {
        grd.addColorStop(index / (node.css.backgroundColor.length - 1), item);
      })
      canvasContext.fillStyle = grd;
    } else {
      canvasContext.fillStyle = node.css.backgroundColor;
    }

    fillRoundRect(canvasContext, node.css.left, node.css.top, node.css.width, node.css.height, node.css.borderRadius);
  }
}

function darwBorder(node: NodeElement) {
  if (node.css.borderWidth === 0 || !node.css.borderColor) {
    return;
  }
  canvasContext.strokeStyle = node.css.borderColor;
  canvasContext.lineWidth = node.css.borderWidth;
  canvasContext.fillStyle = node.css.borderColor;
  roundRect(canvasContext, node.css.left, node.css.top, node.css.width, node.css.height, node.css.borderRadius);

}

async function fillTextNode(node: NodeElement) {

  canvasContext.save();

  //锁定区域


  // clipRoundRect(canvasContext, node.css.left, node.css.top, node.css.width, node.css.height, node.css.borderRadius);

  //填充背景
  if (node.css.width > 0 && node.css.height > 0) {
    canvasContext.save();
    node.css.angle = node.css.angle || 0;
    const angle = node.css.angle;
    canvasContext.translate(node.css.left + node.css.width / 2, node.css.top + node.css.height / 2);
    canvasContext.rotate(angle * Math.PI / 180);
    canvasContext.translate(-(node.css.left + node.css.width / 2), -(node.css.top + node.css.height / 2));

    darwBg(node);
    canvasContext.restore();
  }


  //填充文字
  drawText(node);

  //填充边框
  if (node.css.width > 0 && node.css.height > 0) {
    canvasContext.save();
    node.css.angle = node.css.angle || 0;
    const angle = node.css.angle;
    canvasContext.translate(node.css.left + node.css.width / 2, node.css.top + node.css.height / 2);
    canvasContext.rotate(angle * Math.PI / 180);
    canvasContext.translate(-(node.css.left + node.css.width / 2), -(node.css.top + node.css.height / 2));
    darwBorder(node);
    canvasContext.restore();
  }


  //解锁区域
  canvasContext.restore();

}


function drawShadow(node: NodeElement) {
  if (node.css.shadowColor && node.css.shadowBlur > 0) {
    // canvasContext.setShadow(node.css.shadowOffsetX, node.css.shadowOffsetY, node.css.shadowBlur, node.css.shadowColor);
    canvasContext.shadowOffsetX = node.css.shadowOffsetX;
    canvasContext.shadowOffsetY = node.css.shadowOffsetY;
    canvasContext.shadowColor = node.css.shadowColor;
    canvasContext.shadowBlur = node.css.shadowBlur;
    canvasContext.fillStyle = node.css.shadowColor;
    fillRoundRect(canvasContext, node.css.left, node.css.top, node.css.width, node.css.height, node.css.borderRadius);
    // canvasContext.setShadow(0, 0, 0, 'transparent');
    canvasContext.shadowOffsetX = 0;
    canvasContext.shadowOffsetY = 0;
    canvasContext.shadowColor = 'transparent';
    canvasContext.shadowBlur = 0;
    // canvasContext.shadowColor = 'transparent';
  }
}

function clipPath(node: NodeElement) {
  if (!node.css.clipPath) {
    clipRoundRect(canvasContext, node.css.left, node.css.top, node.css.width, node.css.height, node.css.borderRadius);
  } else {
    //polygon(50% 0, 100% 50%, 50% 100%, 0 50%)
    if (node.css.clipPath.startsWith('polygon')) {
      let clipPathMatchArray = node.css.clipPath.match(/^polygon\((.+)\)$/);
      if (clipPathMatchArray) {
        //50% 0, 100% 50%, 50% 100%, 0 50%
        const points = clipPathMatchArray[1].split(',').map((item) => {
          const tItem = item.replace(/%/g, '')
          let xy = tItem.trim().split(' ');
          return {
            x: (+xy[0] / 100) * node.css.width + node.css.left,
            y: (+xy[1] / 100) * node.css.height + node.css.top,
          }
        });
        canvasContext.beginPath();
        canvasContext.moveTo(points[0].x, points[0].y);
        for (let i = 1; i < points.length; i++) {
          canvasContext.lineTo(points[i].x, points[i].y);
        }
        canvasContext.lineTo(points[0].x, points[0].y);
        canvasContext.closePath();
        canvasContext.clip();
      }
    } else if (node.css.clipPath.startsWith('path')) {
      let clipPathMatchArray = node.css.clipPath.match(/^path\((.+)\)$/);
      if (clipPathMatchArray) {
        //M23.6,0c-3.4,0-6.3,2.7-7.6,5.6C14.7,2.7,11.8,0,8.4,0C3.8,0,0,3.8,0,8.4c0,9.4,9.5,11.9,16,21.2 c6.1-9.3,16-12.1,16-21.2C32,3.8,28.2,0,23.6,0z
        //M512 229.333333a282.666667 282.666667 0 1 1 0 565.333334H282.666667c-29.44 0-53.333333-23.893333-53.333334-53.333334V512A282.666667 282.666667 0 0 1 512 229.333333z m26.666667 312.021334H383.104a5.333333 5.333333 0 0 0-5.333333 5.290666v53.333334c0 2.986667 2.389333 5.376 5.333333 5.376h155.562667a5.333333 5.333333 0 0 0 5.333333-5.376v-53.333334a5.333333 5.333333 0 0 0-5.333333-5.290666z m102.229333-122.709334H383.104a5.333333 5.333333 0 0 0-5.333333 5.376v53.333334c0 2.944 2.389333 5.290667 5.333333 5.290666h257.792a5.333333 5.333333 0 0 0 5.333333-5.290666v-53.333334a5.333333 5.333333 0 0 0-5.333333-5.376z
        let svgPath = new SvgPath(clipPathMatchArray[1]);
        let [svgWidth, svgHeight] = svgPath.size;
        const scaleX = node.css.width / svgWidth;
        const scaleY = node.css.height / svgHeight;
        svgPath.save()
            .beginPath()
            .trim()
            .scale(scaleX, scaleY)
            .translate(node.css.left, node.css.top)
            .to(canvasContext);
        canvasContext.clip();
      }
    }


  }
}

async function drawImageNode(node: NodeElement) {

  //1.锁定区域
  //2.填充背景
  //3.填充图片
  //4.填充边框
  //6.解锁区域
  //7.结束


  canvasContext.save();

  //旋转
  node.css.angle = node.css.angle || 0;
  const angle = node.css.angle;
  canvasContext.translate(node.css.left + node.css.width / 2, node.css.top + node.css.height / 2);
  canvasContext.rotate(angle * Math.PI / 180);
  canvasContext.translate(-(node.css.left + node.css.width / 2), -(node.css.top + node.css.height / 2));

  drawShadow(node);

  //锁定区域
  clipPath(node);

  //填充背景
  darwBg(node);

  //填充图片
  await drawImage(node);

  node.width = node.css.width;
  node.height = node.css.height;

  //填充边框
  darwBorder(node);


  //解锁区域
  canvasContext.restore();


}

let zoom = 1;


const nodesConversion = (nodeElements: NodeElement[]) => {

  nodes = deepClone(nodeElements);

  function _nodesRpx2PxSort(tNodeElements: NodeElement[]) {
    if (tNodeElements == null || tNodeElements.length == 0) {
      return
    }

    tNodeElements.sort((a, b) => {
      const aZindex = a.css.zIndex || 0;
      const bZindex = b.css.zIndex || 0;
      return aZindex - bZindex;
    })
    tNodeElements.forEach((item, index) => {
      item.css.top = rpx2px(item.css.top || 0);
      item.css.left = rpx2px(item.css.left || 0);
      item.css.width = rpx2px(item.css.width || 0);

      item.css.maxWidth = rpx2px(item.css.maxWidth || 0);
      if (item.css.dynamicLocation) {
        item.css.dynamicLocation.offset.left = rpx2px(item.css.dynamicLocation.offset.left || 0);
        item.css.dynamicLocation.offset.top = rpx2px(item.css.dynamicLocation.offset.top || 0);
      }


      item.css.height = rpx2px(item.css.height || 0);
      item.css.borderWidth = rpx2px(item.css.borderWidth || 0);
      item.css.borderRadius = rpx2px(item.css.borderRadius || 0);
      item.css.lineSpacing = rpx2px(item.css.lineSpacing || 0);
      // item.css.font = item.css.font || "32rpx Arial";
      item.css.fontSize = rpx2px(item.css.fontSize || 32);
      item.css.fontFamily = item.css.fontFamily || "SimHei";
      item.css.shadowBlur = rpx2px(item.css.shadowBlur || 0);
      item.css.maxLine = item.css.maxLine || 1;
      item.css.textAlign = item.css.textAlign || 'left';
      item.css.mode = item.css.mode || 'scaleToFill';
      if (item.css.opacity === undefined) {
        item.css.opacity = 1;
      }
      _nodesRpx2PxSort(item.children);
    })
  }

  _nodesRpx2PxSort(nodes);
}

const init = async () => {
  // nodesConversion(props.drawData.nodeElements);

  width = rpx2px(props.drawData.width);
  height = rpx2px(props.drawData.height);

  //加载图标

  // fontFamily.value = fontFamily.value.substring(0, fontFamily.value.length - 1);
  canvas = document.createElement('canvas');
  canvasImage = document.createElement('canvas');
  let element = document.querySelector(`#${id} #${canvasId}`);
  const oCanvas = element.querySelector('canvas');
  canvas.style.width = '100%';
  canvas.style.borderRadius = '0';

  element.insertBefore(canvas, oCanvas);
  oCanvas.remove();
  canvasImage.style.width = '300px';
  canvasImage.style.posize = '100%';
  canvasImage.style.position = 'absolute';
  canvasImage.style.top = '0';
  canvasImage.style.left = '100vw';
  canvasImage.style.zIndex = '-1';
  document.body.append(canvasImage);

  canvas.width = width;
  canvas.height = height;

  canvasContext = canvas.getContext('2d');
  imageCanvasContext = canvasImage.getContext('2d');

}

function pointInRect({x1, y1}, {x, y, width, height, angle}) {

  // 旋转后的矩形的四个顶点坐标
  const rotatedRect = [
    {x: x, y: y},
    {x: x + width, y: y},
    {x: x + width, y: y + height},
    {x: x, y: y + height}
  ];

// 待判断的位置点坐标
  const point = {x: x1, y: y1};

// 旋转中心坐标
  const center = {x: x + width / 2, y: y + height / 2};

// 旋转角度 转弧度
  const angleRadians = angle * Math.PI / 180;

// 将待判断的位置点绕旋转中心逆时针旋转回原始矩形的方向
  const rotatedPoint = {
    x: center.x + (point.x - center.x) * Math.cos(-angleRadians) - (point.y - center.y) * Math.sin(-angleRadians),
    y: center.y + (point.x - center.x) * Math.sin(-angleRadians) + (point.y - center.y) * Math.cos(-angleRadians)
  };

// 判断旋转回去的点是否在未旋转的矩形范围内
  const isInside = (
      rotatedRect[0].x <= rotatedPoint.x && rotatedPoint.x <= rotatedRect[2].x &&
      rotatedRect[0].y <= rotatedPoint.y && rotatedPoint.y <= rotatedRect[2].y
  );

  return isInside;
}


const imageClick = async (e: any) => {
  let {x, y} = e.detail;
  console.log(x, y)
  const clickItems = await getNodeElementByPoint(x, y);
  emit('nodeClick', clickItems);
}

async function getNodeElementByPoint(x: number, y: number) {
  x = x - imageRect.left;
  y = y - imageRect.top;
  const zoom = imageRect.width / width;
  // clickItems.splice(0, clickItems.length);
  let clickItems = [];

  function _nodesRpx2PxSort(tNodeElement: NodeElement) {
    if (tNodeElement.children == null || tNodeElement.children.length == 0) {
      const item = tNodeElement;
      const isClick = pointInRect({x1: x, y1: y},
          {
            x: item.css.left * zoom, y: item.css.top * zoom,
            width: item.width * zoom, height: item.height * zoom,
            angle: item.css.angle
          });
      if (isClick) {
        clickItems.push(item);
      }
      return;
    }
    for (let i = tNodeElement.children.length - 1; i >= 0; i--) {
      const item = tNodeElement.children[i];
      _nodesRpx2PxSort(item);
    }
  }

  try {
    for (let i = nodesDrawFinish.length - 1; i >= 0; i--) {
      const item = nodesDrawFinish[i];
      _nodesRpx2PxSort(item);
    }
  } catch (e) {
  }
  return clickItems;
}

//#ifdef H5
onMounted(() => {
  init();
})
//#endif
onReady(() => {
  init()
})

const id = `id-${Date.now()}`;
</script>

<template>
  <view class="mp-card-canvas" :id="id" :style="{ fontFamily: `${fontFamily}` }">

    <!--    <image :src="image" mode="widthFix" @click="imageClick" id="showImage"></image>-->
    <!--    <view class="load-image" :class="{ 'load-opacity': image }"  :style="{width:width + 'px',height:height + 'px'}">-->
    <!--      <view class="loading"></view>-->
    <!--    </view>-->
    <canvas id="mpCardCanvas" canvas-id="mpCardCanvas" :style="{
      width: `100%`,
      height: `100%`
    }"></canvas>
  </view>
</template>

<style scoped lang="scss">
.mp-card-canvas {
  display: flex;
  justify-content: center;
  align-items: center;
  position: relative;
  width: 100%;
  height: 100%;

  canvas {
    top: 0;
    left: 0;
    z-index: 1;
  }

  image {
    width: 100%;
    opacity: 1;
  }

  .image-opacity {
    opacity: 1;
    /* 设置动画持续时间 */
    transition: opacity 1s;
  }

  .load-opacity {
    opacity: 0;
    /* 设置动画持续时间 */
    transition: opacity 1s;
  }

  .load-image {
    background: #ffffff;
    color: #000;
    display: flex;
    justify-content: center;
    align-items: center;
    position: absolute;
    top: 0;
    left: 0;
    z-index: -1;

    .loading {
      width: 30px;
      height: 30px;
      border: 2px solid #000;
      border-top-color: transparent;
      border-radius: 100%;

      animation: circle infinite 0.75s linear;
    }

    // 转转转动画
    @keyframes circle {
      0% {
        transform: rotate(0);
      }

      100% {
        transform: rotate(360deg);
      }
    }
  }
}
</style>
